package io.wongxd.demo


import org.junit.Test

class StateMachineTest {

    sealed class State {
        object Solid : State()
        object Liquid : State()
        object Gas : State()
    }

    sealed class Event {
        object OnMelted : Event()
        object OnFroze : Event()
        object OnVaporized : Event()
        object OnCondensed : Event()
    }

    sealed class SideEffect {
        object LogMelted : SideEffect()
        object LogFrozen : SideEffect()
        object LogVaporized : SideEffect()
        object LogCondensed : SideEffect()
    }

    private val stateMachine = StateMachine.create<State, Event, SideEffect> {
        initialState(State.Solid)
        state<State.Solid> {
            on<Event.OnMelted> {
                transitionTo(State.Liquid, SideEffect.LogMelted)
            }
        }
        state<State.Liquid> {
            on<Event.OnFroze> {
                transitionTo(State.Solid, SideEffect.LogFrozen)
            }
            on<Event.OnVaporized> {
                transitionTo(State.Gas, SideEffect.LogVaporized)
            }
        }
        state<State.Gas> {
            on<Event.OnCondensed> {
                transitionTo(State.Liquid, SideEffect.LogCondensed)
            }
        }
        onTransition {
            val validTransition = it as? StateMachine.Transition.Valid ?: return@onTransition
            when (validTransition.sideEffect) {
                SideEffect.LogMelted -> println("打印副作用：LogMelted")
                SideEffect.LogFrozen -> println("打印副作用：LogFrozen")
                SideEffect.LogVaporized -> println("打印副作用：LogVaporized")
                SideEffect.LogCondensed -> println("打印副作用：LogCondensed")
                else -> {
                    println("打印副作用：else")
                }
            }
        }
    }

    @Test
    fun `test other`() {
        assert(stateMachine.state == State.Solid)

        // When
        val transition = stateMachine.transition(Event.OnMelted)

        // Then
        assert(stateMachine.state == State.Liquid)
        assert(transition == StateMachine.Transition.Valid(State.Solid, Event.OnMelted, State.Liquid, SideEffect.LogMelted))

    }


}